from django.shortcuts import render
from rest_framework.generics import CreateAPIView
from rest_framework.views import APIView
from rest_framework.response import Response
from django_redis import get_redis_connection
import pickle, base64

from carts.serializers import CartSerialzers, CartGetSerializers, CartDeleteSerialzers, CartSelectionSerialzers
# Create your views here.
# 购物车视图
from goods.models import SKU


class CartsView(APIView):
    """
          保存、删除、获取、修改购物车数据
    """

    def perform_authentication(self, request):
        # 进入到视图调用方法之前先不进行用户登录状态判断
        pass

    def post(self, request):

        # 1、获取前端数据
        data = request.data
        # 2、验证数据
        ser = CartSerialzers(data=data)
        ser.is_valid()
        # 3、获取验证后数据
        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']
        # 4、验证用户是否登录
        try:
            user = request.user
        except Exception as e:
            user = None
        if user is not None:
            # 用户登录  redis
            # 建立redis连接
            conn = get_redis_connection('cart')
            # 写入sku——id和count  hash
            conn.hincrby('cart_%s' % user.id, sku_id, count)
            # 写入选中后状态  set
            if selected:
                conn.sadd('cart_selseted_%s' % user.id, sku_id)
            # 结果返回
            return Response({'message': 'ok'})

        else:
            # 用户未登录  cookie
            # 先获取cookie，判断以前是否写入过cookid
            cart = request.COOKIES.get('cart_cookie', None)
            # 构建响应对象
            response = Response({'message': 'ok'})
            if cart:
                # 获取到cookie，需要对数据解密
                cart = pickle.loads(base64.b64decode(cart))
            else:
                cart = {}

            """
            {
                10:{
                    'count':5,
                    'selected':True
                },
                11:{
                    'count':10,
                    'selected':False
                }
            }
            """

            # 判断sku——id在以前是否存储到cookie
            data = cart.get(sku_id, None)
            # 存储过 需要对数量镜像累加
            if data:
                count += int(data['count'])

            # 写入新数据
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }

            # 加密添加后的字典数据
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()

            # 将加密后的数据写入到cookie中
            response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24 * 7)

            return response

    def get(self, request):

        # 验证用户是否登录
        try:
            user = request.user
        except Exception as e:
            user = None
        if user is not None:
            # 用户登录  redis
            # 建立redis连接
            conn = get_redis_connection('cart')
            # 获取sku——id和count  hash
            sku_count = conn.hgetall('cart_%s' % user.id)
            # 获取选中后状态  set
            sku_selected = conn.smembers('cart_selseted_%s' % user.id)

            # 统一数据格式，将redis中的数据转化为字典嵌套形式
            cart = {}
            for sku_id, count in sku_count.items():
                cart[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in sku_selected
                }

        else:
            # 用户未登录  cookie
            # 先获取cookie，判断以前是否写入过cookid
            cart = request.COOKIES.get('cart_cookie', None)
            # 构建响应对象
            response = Response({'message': 'ok'})
            if cart:
                # 获取到cookie，需要对数据解密
                cart = pickle.loads(base64.b64decode(cart))
            else:
                cart = {}

        # 数据查询处理
        skus = SKU.objects.filter(id__in=cart.keys())
        # 添加属性
        for sku in skus:
            sku.count = cart[sku.id]['count']
            sku.selected = cart[sku.id]['selected']

        # 序列化返回
        ser = CartGetSerializers(skus, many=True)

        return Response(ser.data)

    def put(self, request):

        # 1、获取前端数据
        data = request.data
        # 2、验证数据
        ser = CartSerialzers(data=data)
        ser.is_valid()
        # 3、获取验证后数据
        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']
        # 4、验证用户是否登录
        try:
            user = request.user
        except Exception as e:
            user = None
        if user is not None:
            # 用户登录  redis
            # 建立redis连接
            conn = get_redis_connection('cart')
            # 更新sku_id和count  hash
            conn.hset('cart_%s' % user.id, sku_id, count)
            # 更新选中后状态  set
            if selected:
                conn.sadd('cart_selseted_%s' % user.id, sku_id)
            else:
                conn.srem('cart_selseted_%s' % user.id, sku_id)
            # 结果返回
            return Response(ser.data)

        else:
            # 用户未登录  cookie
            # 先获取cookie，判断以前是否写入过cookie
            cart = request.COOKIES.get('cart_cookie', None)
            # 构建响应对象
            response = Response(ser.data)
            if cart:
                # 获取到cookie，需要对数据解密
                cart = pickle.loads(base64.b64decode(cart))
            else:
                cart = {}

            """
            {
                10:{
                    'count':5,
                    'selected':True
                },
                11:{
                    'count':10,
                    'selected':False
                }
            }
            """
            # 写入新数据
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }

            # 加密添加后的字典数据
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()

            # 将加密后的数据写入到cookie中
            response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24 * 7)

            return response

    def delete(self, request):

        # 1、获取前端数据
        data = request.data
        # 2、验证数据
        ser = CartDeleteSerialzers(data=data)
        ser.is_valid()
        # 3、获取验证后数据
        sku_id = ser.validated_data['sku_id']
        # 4、验证用户是否登录
        try:
            user = request.user
        except Exception as e:
            user = None
        if user is not None:
            # 用户登录  redis
            # 建立redis连接
            conn = get_redis_connection('cart')
            # 删除sku_id和count  hash
            conn.hdel('cart_%s' % user.id, sku_id)
            # 删除选中后状态  set
            conn.srem('cart_selseted_%s' % user.id, sku_id)
            # 结果返回
            return Response({'message': 'ok'})

        else:
            # 用户未登录  cookie
            # 先获取cookie，判断以前是否写入过cookid
            cart = request.COOKIES.get('cart_cookie', None)
            # 构建响应对象
            response = Response({'message': 'ok'})
            if cart:
                # 获取到cookie，需要对数据解密
                cart = pickle.loads(base64.b64decode(cart))

                """
                {
                    10:{
                        'count':5,
                        'selected':True
                    },

                }
                """
                # 删除字典数据
                if sku_id in cart:
                    del cart[sku_id]

                # 加密添加后的字典数据
                cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()

                # 将加密后的数据写入到cookie中
                response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24 * 7)

            return response


# 购物车全选视图类
class CartSelectionView(APIView):

    def perform_authentication(self, request):
        # 进入到视图调用方法之前先不进行用户登录状态判断
        pass

    def put(self, request):

        # 1、获取前端数据
        data = request.data
        # 2、验证数据
        ser = CartSelectionSerialzers(data=data)
        ser.is_valid()
        # 3、获取验证后数据
        selected = ser.validated_data['selected']
        # 4、验证用户是否登录
        try:
            user = request.user
        except Exception as e:
            user = None
        if user is not None:
            # 用户登录  redis
            # 建立redis连接
            conn = get_redis_connection('cart')
            # 获取所有的sku_id
            sku_count = conn.hgetall('cart_%s' % user.id)
            sku_ids = sku_count.keys()

            # 更新选中后状态  set
            if selected:
                conn.sadd('cart_selseted_%s' % user.id, *sku_ids)
            else:
                conn.srem('cart_selseted_%s' % user.id, *sku_ids)
            # 结果返回
            return Response(ser.data)

        else:
            # 用户未登录  cookie
            # 先获取cookie，判断以前是否写入过cookie
            cart = request.COOKIES.get('cart_cookie', None)
            # 构建响应对象
            response = Response(ser.data)
            if cart:
                # 获取到cookie，需要对数据解密
                cart = pickle.loads(base64.b64decode(cart))

                """
                {
                    10:{
                        'count':5,
                        'selected':True
                    },
                    11:{
                        'count':10,
                        'selected':False
                    }
                }
                """
                # 更新字典中的所有选中状态
                for sku_id in cart.keys():
                    cart[sku_id]['selected'] = selected

                # 加密添加后的字典数据
                cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()

                # 将加密后的数据写入到cookie中
                response.set_cookie('cart_cookie', cart_cookie, max_age=60 * 60 * 24 * 7)

            return response
